#include <dict.h>

static char *str_copy(const char *str)
{
    int len = strlen(str);
    char *s = NULL;

    if (str[len - 1] == '\n')
        len--;

    s = (char *)malloc(len + 1);
    ERRP(NULL == s, return NULL, 0);
    bzero(s, len + 1);
    return strncpy(s, str, len);
}

int load_dict(const char *path, DICT *dict)
{
    FILE *fp = NULL;
    char *s = NULL, *en = NULL, *cn = NULL;
    int flag = 0, ret;

    fp = fopen(path, "r");
    ERRP(NULL == fp, goto ERR1, 2, "fopen %s failed!\n", path);

    while (fgets(dict->buf, sizeof(dict->buf), fp) != NULL)
    {
        s = str_copy(dict->buf);
        ERRP(s == NULL, goto ERR2, 2, "malloc str failed!\n");
        if (!flag)
            en = s;
        else
        {
            cn = s;
            ret = list_add(en, cn, &dict->list);
            ERRP(0 == ret, goto ERR3, 2, "list add failed!\n");
            dict->node_num++;
        }
        flag = !flag;
    }

    fclose(fp);

    return 0;
ERR3:
    free(cn);
ERR2:
    if (flag)
        free(en);
    list_destroy(&dict->list);
    fclose(fp);
ERR1:
    return -1;
}

void dis_input(SDLKey key, Uint32 state, void *data)
{
    DICT *dict = (DICT *)data;

    if (dict->input_num + 1 >= INPUT_MAX)
        return;

    dict->input[dict->input_num++] = key;

    dict->input[dict->input_num] = '\0';

    dict->word_num = list_like_find(dict->input, WORD_MAX, dict->word, &dict->list);

    dict_show(dict);
}

void del_input(SDLKey key, Uint32 state, void *data)
{
    DICT *dict = (DICT *)data;

    if (dict->input_num <= 0)
        return;

    dict->input_num--;

    dict->input[dict->input_num] = '\0';

    dict->word_num = list_like_find(dict->input, WORD_MAX, dict->word, &dict->list);

    dict_show(dict);
}

void dict_find(SDLKey key, Uint32 state, void *data)
{
    DICT *dict = (DICT *)data;
    char *cn = NULL;

    dict->input[dict->input_num] = '\0';

    dict->find_cn = hash_find(dict->input, dict->hash);

    /* dict->input_num = 0; */

    dict_show(dict);
}

DICT *dict_init(void)
{
    DICT *dict = NULL;
    int ret, i;

    dict = (DICT *)malloc(sizeof(DICT));
    ERRP(NULL == dict, goto ERR1, 2, "malloc dict failed!\n");

    memset(dict, 0, sizeof(DICT));

    dict->sdl = sdl_init(W, H, BPP, KYO_VIDEO | KYO_TTF);
    ERRP(NULL == dict->sdl, goto ERR2, 2, "malloc dict failed!\n");
    dict->screen = dict->sdl->screen;

    dict->font = TTF_OpenFont(FONT_PATH, FONT_SIZE);
    ERRP(NULL == dict->font, goto ERR2, 2, "ttf open font failed!\n");

    dict->list.next = &dict->list;
    dict->list.prev = &dict->list;

    ret = load_dict(CIKU_PATH, dict);
    ERRP(-1 == ret, goto ERR2, 2, "load_dict failed!\n");

    dict->hash = hash_create(&dict->list, dict->node_num);
    ERRP(NULL == dict->hash, goto ERR2, 2, "create hash list failed!\n");

    dict_show(dict);

    for (i = SDLK_a; i <= SDLK_z; i++)
    {
        sdl_bind_key(dict->sdl, i, SDL_KEYDOWN, dis_input, dict);
    }
    sdl_bind_key(dict->sdl, SDLK_SPACE, SDL_KEYDOWN, dis_input, dict);

    sdl_bind_key(dict->sdl, SDLK_RETURN, SDL_KEYDOWN, dict_find, dict);
    sdl_bind_key(dict->sdl, SDLK_BACKSPACE, SDL_KEYDOWN, del_input, dict);

    return dict;
ERR2:
    dict_exit(dict);
ERR1:
    return NULL;
}

void show_txt(DICT *dict, int x, int y, int w, int h, int color)
{
    SDL_Surface *txt = NULL;
    SDL_Rect offset = {}, txt_offset = {};

    txt = TTF_RenderUTF8_Blended(dict->font, dict->buf, KYO_TO_COLOR(color));

    offset.x = x;
    offset.y = y;
    if (w > 0)
        offset.x += (w - txt->w) / 2;

    if (h > 0)
        offset.y += (h - txt->h) / 2;

    if (w < 0)
        txt_offset.w = -1 * w;
    else
        txt_offset.w = txt->w;

    if (h < 0)
        txt_offset.h = -1 * h;
    else
        txt_offset.h = txt->h;

    SDL_BlitSurface(txt, &txt_offset, dict->screen, &offset);
    SDL_FreeSurface(txt);
}

void dict_show(DICT *dict)
{
    int i;

    draw_rect(dict->screen, 0, 0, W, H, C_BG);
    draw_rect(dict->screen, 0, INPUT_H, W, LINE_W, LINE_COLOR);
    draw_rect(dict->screen, LIKE_W, INPUT_H, LINE_W, LIKE_H, LINE_COLOR);

    if (dict->find_cn)
    {
        snprintf(dict->buf, BUF_MAX, "en: %s", dict->input);
        show_txt(dict, LIKE_W + LINE_W + 10, INPUT_H + LINE_W + 10, 0, 0, FONT_COLOR);
        snprintf(dict->buf, BUF_MAX, "cn: %s", dict->find_cn);
        show_txt(dict, LIKE_W + LINE_W + 10, INPUT_H + LINE_W + 10 + FONT_SIZE, 0, 0, FONT_COLOR);
        dict->find_cn = NULL;
        dict->input_num = 0;
    }
    dict->input[dict->input_num] = '\0';
    snprintf(dict->buf, BUF_MAX, "Input Key: %s", dict->input);
    show_txt(dict, 0, 0, 0, INPUT_H, FONT_COLOR);

    for (i = 0; i < dict->word_num; i++)
    {
        strcpy(dict->buf, dict->word[i]);
        show_txt(dict, 0, INPUT_H + 12 + i * FONT_SIZE, -(LIKE_W - 10), 0, FONT_COLOR);
    }

    SDL_Flip(dict->screen);
}

int dict_run(DICT *dict, int isexit)
{
    sdl_run(dict->sdl, 0);

    if (isexit)
        dict_exit(dict);

    return 0;
}

void dict_exit(DICT *dict)
{
    if (dict->hash)
        hash_destroy(dict->hash);
    if (dict->node_num)
        list_destroy(&dict->list);
    if (dict->font)
        TTF_CloseFont(dict->font);
    if (dict->sdl)
        sdl_exit(&dict->sdl);
    free(dict);
}


